var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
    for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
        to[j] = from[i];
    return to;
};
var hmacSHA256 = require('crypto-js/hmac-sha256');
var SignerBase = /** @class */ (function () {
    function SignerBase(EndpointUri, HttpMethod, Service, Region) {
        this.EndpointUri = EndpointUri;
        this.HttpMethod = HttpMethod;
        this.Service = Service;
        this.Region = Region;
        // SHA256 hash of an empty request body
        this.EMPTY_BODY_SHA256 = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
        this.SCHEME = 'AWS4';
        this.ALGORITHM = 'HMAC-SHA256';
        this.TERMINATOR = 'aws4_request';
        // format strings for the date/time and date stamps required during signing
        this.ISO8601BasicFormat = 'yyyyMMddThhmmssZ';
        this.DateStringFormat = 'yyyyMMdd';
        // some common x-amz-* parameters
        this.X_Amz_Algorithm = 'X-Amz-Algorithm';
        this.X_Amz_Credential = 'X-Amz-Credential';
        this.X_Amz_SignedHeaders = 'X-Amz-SignedHeaders';
        this.X_Amz_Date = 'X-Amz-Date';
        this.X_Amz_Signature = 'X-Amz-Signature';
        this.X_Amz_Expires = 'X-Amz-Expires';
        this.X_Amz_Content_SHA256 = 'X-Amz-Content-SHA256';
        this.X_Amz_Decoded_Content_Length = 'X-Amz-Decoded-Content-Length';
        this.X_Amz_Meta_UUID = 'X-Amz-Meta-UUID';
        // the name of the keyed hash algorithm used in signing
        this.HMACSHA256 = 'HMACSHA256';
    }
    /// <summary>
    /// Returns the canonical collection of header names that will be included in
    /// the signature. For AWS4, all header names must be included in the process
    /// in sorted canonicalized order.
    /// </summary>
    /// <param name="headers">
    /// The set of header names and values that will be sent with the request
    /// </param>
    /// <returns>
    /// The set of header names canonicalized to a flattened, ;-delimited string
    /// </returns>
    SignerBase.prototype.CanonicalizeHeaderNames = function (headers) {
        var headersToSign = __spreadArray([], __read(headers.keys())).map(function (i) { return i.toLowerCase(); });
        headersToSign.sort(function (a, b) { return (a < b ? -1 : 1); });
        return headersToSign.join(';');
    };
    /// <summary>
    /// Computes the canonical headers with values for the request.
    /// For AWS4, all headers must be included in the signing process.
    /// </summary>
    /// <param name="headers">The set of headers to be encoded</param>
    /// <returns>Canonicalized string of headers with values</returns>
    SignerBase.prototype.CanonicalizeHeaders = function (headers) {
        if (headers.size == 0)
            return '';
        // step1: sort the headers into lower-case format; we create a new
        // map to ensure we can do a subsequent key lookup using a lower-case
        // key regardless of how 'headers' was created.
        var sortedHeaderKey = __spreadArray([], __read(headers.keys()));
        sortedHeaderKey.sort(function (a, b) { return (a.toLowerCase() < b.toLowerCase() ? -1 : 1); });
        // step2: form the canonical header:value entries in sorted order.
        // Multiple white spaces in the values should be compressed to a single
        // space.
        var str = '';
        sortedHeaderKey.forEach(function (item) {
            var headerValue = headers
                .get(item)
                .replace(SignerBase.CompressWhitespaceRegex, ' ');
            str += item.toLowerCase() + ":" + headerValue.trim() + "\n";
        });
        return str;
    };
    /// <summary>
    /// Returns the canonical request string to go into the signer process; this
    /// consists of several canonical sub-parts.
    /// </summary>
    /// <param name="endpointUri"></param>
    /// <param name="httpMethod"></param>
    /// <param name="queryParameters"></param>
    /// <param name="canonicalizedHeaderNames">
    /// The set of header names to be included in the signature, formatted as a flattened, ;-delimited string
    /// </param>
    /// <param name="canonicalizedHeaders">
    /// </param>
    /// <param name="bodyHash">
    /// Precomputed SHA256 hash of the request body content. For chunked encoding this
    /// should be the fixed string ''.
    /// </param>
    /// <returns>String representing the canonicalized request for signing</returns>
    SignerBase.prototype.CanonicalizeRequest = function (endpointUri, httpMethod, queryParameters, canonicalizedHeaderNames, canonicalizedHeaders, bodyHash) {
        return httpMethod + "\n" + SignerBase.CanonicalResourcePath(endpointUri) + "\n" + queryParameters + "\n" + canonicalizedHeaders + "\n" + canonicalizedHeaderNames + "\n" + bodyHash;
    };
    /// <summary>
    /// Returns the canonicalized resource path for the service endpoint
    /// </summary>
    /// <param name="endpointUri">Endpoint to the service/resource</param>
    /// <returns>Canonicalized resource path for the endpoint</returns>
    SignerBase.CanonicalResourcePath = function (endpointUri) {
        var absolutePath = endpointUri.pathname;
        return absolutePath ? encodeURI(absolutePath) : '/';
    };
    /// <summary>
    /// Compute and return the multi-stage signing key for the request.
    /// </summary>
    /// <param name="algorithm">Hashing algorithm to use</param>
    /// <param name="awsSecretAccessKey">The clear-text AWS secret key</param>
    /// <param name="region">The region in which the service request will be processed</param>
    /// <param name="date">Date of the request, in yyyyMMdd format</param>
    /// <param name="service">The name of the service being called by the request</param>
    /// <returns>Computed signing key</returns>
    SignerBase.prototype.DeriveSigningKey = function (awsSecretAccessKey, date) {
        return hmacSHA256(this.TERMINATOR, hmacSHA256(this.Service, hmacSHA256(this.Region, hmacSHA256(date, this.SCHEME + awsSecretAccessKey))));
    };
    // request canonicalization requires multiple whitespace compression
    SignerBase.CompressWhitespaceRegex = /\\s+/;
    // algorithm used to hash the canonical request that is supplied to
    // the signature computation
    SignerBase.CanonicalRequestHashAlgorithm = hmacSHA256;
    return SignerBase;
}());
export default SignerBase;
